<!--
vue3、vue2 基于 kite-captcha 验证组件
author：stary1993 https://gitee.com/stary1993
依赖：ajxos ajxos-vue、element ui、animate.css
服务端生成：https://gitee.com/kite/kite-captcha

-->
<template>
  <div v-if="show" id="kite-captcha-parent">
    <div id="kite-captcha-bg-img" :style="{backgroundImage: 'url('+this.backgroundImage+')'}"></div>
    <div id="kite-captcha-box">
      <img v-show="loading" id="kite-captcha-loading"
           alt="loading"
           src="">
      <div v-if="type === 'SLIDER'" id="kite-captcha" :class="captchaClass"
           class="kite-captcha-slider animate__animated">
        <div class="kite-slider-tips">
          <span>拖动滑块完成拼图</span>
        </div>
        <div class="kite-captcha-content">
          <div id="kite-captcha-bg-img-box" class="kite-captcha-bg-img-box">
            <img id="kite-slider-bg-img" :src="data.backgroundImage" alt/>
            <canvas id="kite-captcha-slider-bg-canvas"></canvas>
          </div>
          <div id="kite-slider-move-img-box" :style="sliderImgStyles" class="kite-slider-move-img-box">
            <img id="kite-captcha-slider-move-img" :src="data.templateImage" alt="">
          </div>
          <div id="kite-captcha-tips" :class="tipsClass" class="kite-captcha-tips">{{ tipsContent }}</div>
        </div>
        <div class="kite-slider-move">
          <div class="kite-slider-move-track">
            <div id="kite-captcha-slider-move-track-mask"
                 :style="moveTracMaskStyles"
                 style="border-color: rgb(2, 152, 248); background-color: rgb(137, 210, 255);"></div>
            <div class="kite-slider-move-shadow"></div>
          </div>
          <div id="kite-captcha-slider-move-btn"
               :style="moveBtnStyles"
               class="kite-slider-move-btn"
               style="background-image: url('');"
               @mousedown="$_slider_down($event)"
               @touchstart="$_slider_down($event)">
          </div>
        </div>
      </div>
      <div v-else-if="type === 'ROTATE'" id="kite-captcha" :class="captchaClass"
           class="kite-captcha-slider kite-captcha-rotate animate__animated">
        <div class="kite-slider-tips">
          <span>拖动滑块完成拼图</span>
        </div>
        <div class="kite-captcha-content">
          <div id="kite-captcha-bg-img-box" class="kite-captcha-bg-img-box">
            <img id="kite-slider-bg-img" :src="data.backgroundImage" alt/>
            <canvas id="kite-captcha-slider-bg-canvas"></canvas>
          </div>
          <div id="kite-slider-move-img-box" class="kite-slider-move-img-box">
            <img id="kite-captcha-slider-move-img" :src="data.templateImage" :style="rotateImgStyles" alt="">
          </div>
          <div id="kite-captcha-tips" :class="tipsClass" class="kite-captcha-tips">{{ tipsContent }}</div>
        </div>
        <div class="kite-slider-move">
          <div class="kite-slider-move-track">
            <div id="kite-captcha-slider-move-track-mask"
                 :style="moveTracMaskStyles"
                 style="border-color: rgb(2, 152, 248); background-color: rgb(137, 210, 255);"></div>
            <div class="kite-slider-move-shadow"></div>
          </div>
          <div id="kite-captcha-slider-move-btn"
               :style="moveBtnStyles"
               class="kite-slider-move-btn"
               style="background-image: url('');"
               @mousedown="$_slider_down($event)"
               @touchstart="$_slider_down($event)">
          </div>
        </div>
      </div>
      <div v-else-if="type === 'CONCAT'" id="kite-captcha" :class="captchaClass"
           class="kite-captcha-slider kite-captcha-concat animate__animated">
        <div class="kite-slider-tips">
          <span>拖动滑块完成拼图</span>
        </div>
        <div class="kite-captcha-content">
          <div id="kite-captcha-slider-concat-img" :style="concatImgStyles" class="kite-captcha-slider-concat-img">
            <img id="kite-captcha-slider-concat-slider-img" alt/>
          </div>
          <div id="kite-captcha-slider-concat-bg-img" :style="concatBgImgStyles"
               class="kite-captcha-slider-concat-bg-img"></div>
          <div id="kite-captcha-tips" :class="tipsClass" class="kite-captcha-tips">{{ tipsContent }}</div>
        </div>
        <div class="kite-slider-move">
          <div class="kite-slider-move-track">
            <div id="kite-captcha-slider-move-track-mask"
                 :style="moveTracMaskStyles"
                 style="border-color: rgb(2, 152, 248); background-color: rgb(137, 210, 255);"></div>
            <div class="kite-slider-move-shadow"></div>
          </div>
          <div id="kite-captcha-slider-move-btn"
               :style="moveBtnStyles"
               class="kite-slider-move-btn"
               style="background-image: url('');"
               @mousedown="$_slider_down($event)"
               @touchstart="$_slider_down($event)">
          </div>
        </div>
      </div>
      <div v-else-if="type === 'WORD_IMAGE_CLICK'" id="kite-captcha" :class="captchaClass"
           class="kite-captcha-slider kite-captcha-work-click animate__animated">
        <div class="kite-work-click-tips">
          <span>请依次点击：</span>
          <img id="kite-work-click-tip-img" :src="wordImgData.tipImage" class="kite-work-click-tip-img">
        </div>
        <div class="kite-captcha-content" @click="$_word_click">
          <div class="kite-captcha-bg-img-box">
            <img id="kite-captcha-work-click-bg-img" :src="wordImgData.backgroundImage"
                 class="kite-captcha-work-click-bg-img">
            <canvas id="kite-captcha-slider-bg-canvas"></canvas>
            <div id="kite-bg-img-click-mask">
              <span
                  v-for="item in clickData"
                  :key="'click_' + item.count"
                  :style="{left: item.left, top: item.top }"
                  class="click-span"
              >{{ item.count }}</span>
            </div>
          </div>
          <div id="kite-captcha-tips" :class="tipsClass" class="kite-captcha-tips">{{ tipsContent }}</div>
        </div>
      </div>

    </div>

    <div class="kite-captcha-slider-bottom">
      <img alt="captcha-logo"
           class="kite-captcha-logo"
           src=""/>
      <el-tooltip class="item" content="关闭" effect="dark" placement="top">
        <div v-show="showClose" class="kite-close-btn" @click="$_close"></div>
      </el-tooltip>
      <el-tooltip class="item" content="刷新" effect="dark" placement="top">
        <div class="kite-refresh-btn" @click="$_refresh"></div>
      </el-tooltip>
      <el-tooltip class="item" content="欢迎使用验证码组件" effect="dark" placement="top">
        <div class="kite-info-btn"></div>
      </el-tooltip>
    </div>
  </div>

</template>

<script>

export default {
  name: 'Captcha',
  props: {
    /**
     * 是否显示
     */
    defaultShow: {type: Boolean, default: false},
    /**
     * 加载动画
     */
    loadingAnimation: {type: String, default: 'slide'},
    /**
     * 生成url
     */
    defaultGenUrl: {type: String, default: '/captcha/gen'},
    /**
     * 验证url
     */
    defaultCheckUrl: {type: String, default: '/captcha/check'},
    /**
     * 验证码类型
     */
    defaultType: {type: String, default: 'SLIDER'},
    /**
     * 背景图
     */
    backgroundImage: {type: String, default: null},
    /**
     * 是否显示关闭按钮
     */
    showClose: {type: Boolean, default: true}
  },
  data() {
    return {
      TYPES: ['SLIDER', 'ROTATE', 'CONCAT', 'WORD_IMAGE_CLICK'],
      LOADING_ANIMATION: ['slide', 'bounce', 'fade', 'lightSpeed', 'zoom'],
      data: {
        backgroundImage: null,
        backgroundImageWidth: 0,
        backgroundImageHeight: 0,
        sliderImageWidth: 0,
        sliderImageHeight: 0,
        templateImage: null,
        id: null,
        data: null
      },
      genUrl: this.defaultGenUrl,
      type: this.defaultType,
      checkUrl: this.defaultCheckUrl,
      checkData: {
        id: null,
        track: null
      },
      startX: 0,
      startY: 0,
      end: 0,
      moveX: 0,
      movePercent: 0,
      // 滑动轨迹滑动时间等数据
      trackData: {
        bgImageWidth: 0,
        bgImageHeight: 0,
        sliderImageWidth: 0,
        sliderImageHeight: 0,
        startSlidingTime: null,
        endSlidingTime: null,
        trackList: []
      },
      captchaClass: null,
      moveTracMaskStyles: {
        width: 0
      },
      // 移动按钮样式
      moveBtnStyles: {
        transform: 'translateX(0)',

      },
      // 滑动样式
      sliderImgStyles: {
        transform: 'translateX(0)'
      },
      // 旋转样式
      rotateImgStyles: {
        transform: 'rotate(0deg)'
      },
      // 滚动还原样式
      concatImgStyles: {
        height: 0,
        backgroundImage: null,
        backgroundPosition: '0px 0px'
      },
      // 滚动还原背景图片
      concatBgImgStyles: {
        backgroundImage: null
      },
      // 文字点击数据
      wordImgData: {
        backgroundImage: null,
        tipImage: null
      },
      // 文字点击数据
      clickData: [{}],
      show: this.defaultShow,
      loading: false,
      tipsContent: null,
      tipsClass: null,
      activeTime: {
        startTime: null,
        endTime: null
      },
      renderSuccess: false
    }
  },
  methods: {
    $_init() {
      let bgElement = document.getElementById('kite-captcha-bg-img-box')
      if (!bgElement) {
        bgElement = document.getElementById('kite-captcha-slider-concat-bg-img')
      }
      const sliderMoveBtnElement = document.getElementById('kite-captcha-slider-move-btn')
      this.trackData.bgImageWidth = bgElement.clientWidth
      this.trackData.bgImageHeight = bgElement.clientHeight
      this.end = this.trackData.bgImageWidth - sliderMoveBtnElement.clientWidth
      if (this.type === 'ROTATE') {
        this.trackData.sliderImageWidth = this.trackData.bgImageHeight
        this.trackData.sliderImageHeight = this.trackData.bgImageHeight
        this.trackData.bgImageWidth = this.end
      }
    },
    /**
     * 生成滑动验证图片
     */
    async $_gen(type) {
      this.show = true
      this.loading = true
      if (!type) {
        type = this.defaultType
      }
     await this.$http.get(`${this.genUrl}?type=${type}`).then(res => {
        setTimeout(()=>this.$_render(res), 1000)
      })
    },
    /**
     * 验证
     */
    $_check() {
      this.trackData.startSlidingTime = this.getNowDate(this.trackData.startSlidingTime)
      this.trackData.endSlidingTime = this.getNowDate(this.trackData.endSlidingTime)
      if (this.type === 'WORD_IMAGE_CLICK') {
        const clickContent = document.getElementById('kite-bg-img-click-mask')
        const tipContent = document.getElementById('kite-work-click-tip-img')
        this.trackData.bgImageHeight = clickContent.clientHeight
        this.trackData.bgImageWidth = clickContent.clientWidth
        this.trackData.sliderImageWidth = tipContent.clientWidth
        this.trackData.sliderImageHeight = tipContent.clientHeight
      }
      console.log(JSON.stringify(this.trackData))
      this.$http.post(`${this.checkUrl}?id=${this.checkData.id}`, this.trackData).then(res => {
        const result = res.data
        const code = result.code
        this.$emit('check-result', result)
        this.activeTime.endTime = new Date().getTime();
        if (code === 4000) {
          this.tipsError("验证码被黑洞吸走了")
          setTimeout(this.$_refresh, 1000)
          return
        }
        if (code === 200) {
          this.tipsSuccess();
          // this.$_close()
          // this.$alert('验证成功','验证结果',{callback: this.$_close()})
          return
        }
        this.tipsError()
        //this.$message.error('验证失败')
        setTimeout(this.$_refresh, 1000)

      }).catch(() => {
        this.tipsError()
        setTimeout(this.$_refresh, 1000)
      })

    },
    /**
     * 刷新
     */
    $_refresh(type) {
      this.captchaClass = `animate__${this.loadingAnimation}OutRight`
      this.$_gen(type)
    },
    /**
     * 重置
     */
    $_reset() {
      this.moveBtnStyles.transform = 'translateX(0)'
      this.moveTracMaskStyles.width = 0
      this.sliderImgStyles.transform = 'translateX(0)'
      this.rotateImgStyles.transform = 'rotate(0deg)'
      this.concatImgStyles.backgroundPosition = '0px 0px'
      this.concatImgStyles.backgroundImage = null
      this.concatImgStyles.height = 0
      this.wordImgData.backgroundImage = null
      this.wordImgData.tipImage = null
      this.end=0
      this.startX = 0
      this.startY = 0
      this.moveX = 0
      this.movePercent = 0
      this.checkData.track = null
      this.checkData.id = null
      this.data.id = null
      this.trackData.startSlidingTime = null
      this.trackData.endSlidingTime = null

      this.trackData.trackList = []
      this.clickCount = 0
      this.clickData = []
      this.tipsContent = ''
      this.tipsClass = null
      this.captchaClass = null
      this.renderSuccess = false
      window.removeEventListener('mousemove', this.$_move)

    },
    $_close() {
      this.show = false
    },

    /*
     * 滑动图片鼠标按下
     */
    $_slider_down(event) {
      this.$_init()
      this.activeTime.startTime = new Date().getTime();
      const targetTouches = event.originalEvent ? event.originalEvent.targetTouches : event.targetTouches
      let startX = event.pageX
      let startY = event.pageY
      if (startX === undefined) {
        startX = Math.round(targetTouches[0].pageX)
        startY = Math.round(targetTouches[0].pageY)
      }
      this.startX = startX
      this.startY = startY

      const pageX = this.startX
      const pageY = this.startY
      const startTime = this.trackData.startSlidingTime
      const trackArr = this.trackData.trackList
      trackArr.push({
        x: pageX - startX,
        y: pageY - startY,
        type: 'down',
        t: (new Date().getTime() - startTime.getTime())
      })
      console.log('start', startX, startY)
      // pc
      window.addEventListener('mousemove', this.$_move)
      window.addEventListener('mouseup', this.$_up)
      // 手机端
      window.addEventListener('touchmove', this.$_move, false)
      window.addEventListener('touchend', this.$_up, false)

    },
    /**
     * 移动
     * @param event
     */
    $_move(event) {
      if (event instanceof TouchEvent) {
        event = event.touches[0]
      }
      const pageX = Math.round(event.pageX)
      const pageY = Math.round(event.pageY)
      const startX = this.startX
      const startY = this.startY
      const startTime = this.trackData.startSlidingTime
      const end = this.end
      const bgImageWidth = this.trackData.bgImageWidth
      const trackList = this.trackData.trackList
      let moveX = pageX - startX
      const track = {
        x: pageX - startX,
        y: pageY - startY,
        type: 'move',
        t: (new Date().getTime() - startTime.getTime())
      }
      trackList.push(track)
      if (moveX < 0) {
        moveX = 0
      } else if (moveX > end) {
        moveX = end
      }
      this.moveX = moveX
      this.movePercent = moveX / bgImageWidth

      this.moveTracMaskStyles.width = moveX + 'px'
      this.moveBtnStyles.transform = 'translateX(' + moveX + 'px)'
      this.sliderImgStyles.transform = 'translateX(' + moveX + 'px)'
      this.rotateImgStyles.transform = 'rotate(' + (moveX / (end / 360)) + 'deg)'
      this.concatImgStyles.backgroundPosition = (moveX + 'px 0px')
      console.log('move', JSON.stringify(track))
    },
    /**
     * 鼠标松下,进行验证
     * @param event
     */
    $_up(event) {
      window.removeEventListener('mousemove', this.$_move)
      window.removeEventListener('mouseup', this.$_up)
      window.removeEventListener('touchmove', this.$_move)
      window.removeEventListener('touchend', this.$_up)
      if (event instanceof TouchEvent) {
        event = event.changedTouches[0]
      }
      this.trackData.endSlidingTime = new Date()
      const pageX = Math.round(event.pageX)
      const pageY = Math.round(event.pageY)
      const startX = this.startX
      const startY = this.startY
      const startTime = this.trackData.startSlidingTime
      const trackList = this.trackData.trackList

      const track = {
        x: pageX - startX,
        y: pageY - startY,
        type: 'up',
        t: (new Date().getTime() - startTime.getTime())
      }
      trackList.push(track)
      console.log('up', JSON.stringify(track))
      this.$emit('move-stop', this.checkData)
      this.$_check()
    },
    /**
     * 点击文字
     */
    $_word_click(event) {
      this.clickCount++
      if (this.clickCount === 1) {
        this.activeTime.startTime = new Date().getTime();
        this.trackData.startSlidingTime = new Date()
        // move 轨迹
        window.addEventListener('mousemove', this.$_word_move)
      }
      const trackList = this.trackData.trackList
      trackList.push({
        x: event.offsetX,
        y: event.offsetY,
        type: 'click',
        t: (new Date().getTime() - this.trackData.startSlidingTime.getTime())
      })
      const left = event.offsetX - 10
      const top = event.offsetY - 10
      const clickData = this.clickData
      clickData.push({
        count: this.clickCount,
        left: left + 'px',
        top: top + 'px'
      })

      if (this.clickCount === 4) {
        // 校验
        this.trackData.endSlidingTime = new Date()
        window.removeEventListener('mousemove', this.$_word_move)
        this.checkData.track = this.trackData
        this.$emit('move-stop', this.checkData)
        this.$_check()
      }
    },
    /**
     * 文字点击移动
     * @param event
     */
    $_word_move(event) {
      if (event instanceof TouchEvent) {
        event = event.touches[0]
      }
      console.log('x:', event.offsetX, 'y:', event.offsetY, 'time:', new Date().getTime() - this.trackData.startSlidingTime.getTime())
      const trackList = this.trackData.trackList
      trackList.push({
        x: event.offsetX,
        y: event.offsetY,
        t: (new Date().getTime() - this.trackData.startSlidingTime.getTime()),
        type: 'move'
      })
    },
    getNowDate(date) {
      const dt = date
      const y = dt.getFullYear()
      const m = (dt.getMonth() + 1 + '').padStart(2, 0)
      const d = (dt.getDate() + '').padStart(2, 0)
      const hh = (dt.getHours() + '').padStart(2, 0)
      const mm = (dt.getMinutes() + '').padStart(2, 0)
      const ss = (dt.getSeconds() + '').padStart(2, 0)
      const sss = (dt.getMilliseconds() + '').padStart(2, 0)
      return `${y}-${m}-${d} ${hh}:${mm}:${ss}.${sss}`

    },
    /**
     * 切换验证方式
     * @param type
     */
    changeType(type) {

      if (type === 'RANDOM') {
        const randomNum = Math.floor(Math.random() * (this.TYPES.length - 1))
        type = this.TYPES[randomNum]
      }
      this.$_refresh(type)
    },
    tipsError(msg) {
      this.tipsContent = msg ? msg : '验证失败，请重新尝试';
      this.tipsClass = 'tips-error tips-on'
    },
    tipsSuccess() {
      const sec = (this.activeTime.endTime - this.activeTime.startTime) / 1000
      this.tipsContent = `验证成功，耗时${sec}秒`
      this.tipsClass = 'tips-success tips-on'
    },
    $_render(res) {
      this.$_reset()
      this.data = res.data.captcha
      this.data.id = res.data.id
      this.checkData.id = this.data.id
      this.type = this.data.type
      this.loading = false
      let sliderElement = document.getElementById('kite-captcha-slider-move-img')
      if (!sliderElement) {
        sliderElement = document.getElementById('kite-captcha-slider-concat-img')
      }
      if (!sliderElement && this.type !== 'WORD_IMAGE_CLICK') {
        this.trackData.sliderImageWidth = sliderElement.clientWidth
        this.trackData.sliderImageHeight = sliderElement.clientHeight
      }

      if (this.type === 'CONCAT') {
        this.concatBgImgStyles.backgroundImage = 'url(' + this.data.backgroundImage + ')'
        const backgroundImageHeight = this.data.backgroundImageHeight
        const height = ((backgroundImageHeight - this.data.data.randomY) / backgroundImageHeight) * 180
        this.concatImgStyles.backgroundImage = 'url(' + this.data.backgroundImage + ')'
        this.concatImgStyles.height = height + 'px'
        const bgImg = document.getElementById('kite-captcha')
        this.trackData.bgImageWidth = bgImg.clientWidth
        this.trackData.bgImageHeight = bgImg.clientHeight
      } else if (this.type === 'WORD_IMAGE_CLICK') {
        this.wordImgData.backgroundImage = this.data.backgroundImage
        this.wordImgData.tipImage = this.data.templateImage
      }

      this.trackData.startSlidingTime = new Date()
      console.log('init', JSON.stringify(this.trackData))
      this.renderSuccess = true
      this.$emit('render-success', this.renderSuccess)
      this.captchaClass = `animate__${this.loadingAnimation}InLeft`
    }
  }
}
</script>

<style scoped>
/** global css start **/
#kite-captcha-parent {
  box-shadow: 0 0 11px 0 #999;
  width: 318px;
  height: 318px;
  overflow: hidden;
  position: relative;
  z-index: 997;
  box-sizing: border-box;
  border-radius: 5px;
  padding: 8px;
}

/*背景图*/
#kite-captcha-parent #kite-captcha-bg-img {
  background-position: top;
  background-size: cover;
  background-repeat: no-repeat;
  z-index: -1;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  position: absolute;
  border-radius: 6px;
  background-color: #fff;
}

/*验证码主体*/
#kite-captcha-parent #kite-captcha-box {
  height: 260px;
  width: 100%;
  position: relative;
  overflow: hidden;
}

/*加载图*/
#kite-captcha-parent #kite-captcha-box #kite-captcha-loading {
  width: 50px;
  height: 50px;
  text-align: center;
  z-index: 998;
  position: absolute;
  top: 120px;
  left: 126px;
  -moz-user-select: none;
  -webkit-user-select: none;
  user-select: none;
}

#kite-captcha-parent #kite-captcha-box #kite-captcha {
  text-align: left;
  box-sizing: content-box;
  width: 300px;
  height: 260px;
}

#kite-captcha.kite-captcha-slider {
  z-index: 999;
  position: absolute;
  left: 0;
  top: 0;
  user-select: none;
}

#kite-captcha-parent #kite-captcha-slider-move-track-mask {
  border-width: 1px;
  border-style: solid;
  border-color: #00f4ab;
  width: 0;
  height: 32px;
  background-color: #a9ffe5;
  opacity: .5;
  position: absolute;
  top: -1px;
  left: -1px;
  border-radius: 5px;
}

/*验证码底部*/
#kite-captcha-parent .kite-captcha-slider-bottom {
  height: 19px;
  width: 100%;
}

/*logo图*/
#kite-captcha-parent .kite-captcha-slider-bottom .kite-captcha-logo {
  height: 30px;
  float: left;
}

#kite-captcha-parent .kite-captcha-slider-bottom .kite-close-btn, .kite-refresh-btn, .kite-info-btn {
  width: 20px;
  height: 20px;
  float: right;
  margin-right: 10px;
  cursor: pointer;
  background-repeat: no-repeat;
  background-size: cover;
}

#kite-captcha-parent .kite-captcha-slider-bottom .kite-close-btn {
  background-image: url('');

}

#kite-captcha-parent .kite-captcha-slider-bottom .kite-refresh-btn {
  background-image: url('');
}

#kite-captcha-parent .kite-captcha-slider-bottom .kite-info-btn {
  background-image: url('');
}

#kite-captcha-parent #kite-captcha .kite-captcha-tips {
  height: 25px;
  width: 100%;
  position: absolute;
  bottom: -25px;
  left: 0;
  z-index: 999;
  font-size: 15px;
  line-height: 25px;
  color: #fff;
  text-align: center;
  transition: bottom .3s ease-in-out;
}

#kite-captcha-parent #kite-captcha .kite-captcha-tips.tips-error {
  background-color: #ff5d39
}

#kite-captcha-parent #kite-captcha .kite-captcha-tips.tips-success {
  background-color: #39c522
}

#kite-captcha-parent #kite-captcha .kite-captcha-tips.tips-on {
  bottom: 0 !important;
}

@keyframes myanimation {
  from {
    left: 0
  }
  to {
    left: 289px
  }
}

/** global css end **/

/** slider css start **/
#kite-captcha.kite-captcha-slider {
  z-index: 999;
  position: absolute;
  left: 0;
  top: 0;
  user-select: none;
}

#kite-captcha.kite-captcha-slider .kite-slider-tips {
  margin-bottom: 5px;
  font-weight: bold;
  font-size: 15px;
  line-height: normal;
  color: #000;
}

#kite-captcha.kite-captcha-slider .kite-captcha-content {
  width: 100%;
  height: 180px;
  position: relative;
  overflow: hidden;
}

#kite-captcha.kite-captcha-slider .kite-captcha-bg-img-box {
  width: 100%;
  height: 100%;
  position: absolute;
  transform: translate(0px, 0px);
}

#kite-captcha.kite-captcha-slider .kite-captcha-bg-img-box img {
  height: 100%;
  border-radius: 5px;
}

#kite-captcha #kite-captcha-slider-bg-canvas {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  border-radius: 5px;
}

#kite-captcha.kite-captcha-slider .kite-slider-move-img-box {
  height: 100%;
  position: absolute;
  transform: translate(0px, 0px);
}

#kite-captcha.kite-captcha-slider .kite-slider-move-img-box img#kite-captcha-slider-move-img {
  height: 100%;
}

#kite-captcha.kite-captcha-slider .kite-slider-move {
  height: 34px;
  width: 100%;
  margin: 11px 0;
  position: relative;
}

#kite-captcha.kite-captcha-slider .kite-slider-move .kite-slider-move-track {
  position: relative;
  height: 32px;
  line-height: 32px;
  text-align: center;
  background: #f5f5f5;
  color: #999;
  transition: 0s;
  font-size: 14px;
  box-sizing: content-box;
  border: 1px solid #f5f5f5;
  border-radius: 4px;
}

#kite-captcha.kite-captcha-slider .kite-slider-move .kite-slider-move-track .kite-slider-move-shadow {
  animation: myanimation 2s infinite;
  height: 100%;
  width: 5px;
  background-color: #fff;
  position: absolute;
  top: 0;
  left: 0;
  filter: opacity(0.5);
  box-shadow: 1px 1px 1px #fff;
  border-radius: 50%;
}

#kite-captcha.kite-captcha-slider .kite-slider-move .kite-slider-move-btn {
  transform: translate(0px, 0px);
  position: absolute;
  top: -6px;
  left: 0;
  width: 63px;
  height: 45px;
  background-color: #fff;
  background-repeat: no-repeat;
  background-size: contain;
  border-radius: 5px;
}

#kite-captcha.kite-captcha-slider .kite-slider-move .kite-slider-move-btn:hover {
  cursor: pointer;
}

/** slider css end **/

/** rotate css start **/
#kite-captcha.kite-captcha-rotate .kite-slider-move-img-box {
  height: 100%;
  text-align: center;
  position: initial;
}

#kite-captcha.kite-captcha-rotate .kite-slider-move-img-box img#kite-captcha-slider-move-img {
  height: 100%;
  transform: rotate(0deg);
  display: inline-block;
}

/** rotate css end **/

/** concat css start **/
#kite-captcha.kite-captcha-concat .kite-captcha-slider-concat-img {
  background-size: 100% 180px;
  position: absolute;
  transform: translate(0px, 0px);
  z-index: 1;
  width: 100%;
}

#kite-captcha.kite-captcha-concat .kite-captcha-slider-concat-bg-img {
  width: 100%;
  height: 100%;
  position: absolute;
  transform: translate(0px, 0px);
  background-size: 100% 180px;
}

/** concat css end **/

/** word_click css start **/
#kite-captcha.kite-captcha-work-click {
  position: relative;
  box-sizing: border-box;
}

#kite-captcha .kite-work-click-tips {
  position: relative;
  height: 40px;
  width: 100%;
}

#kite-captcha .kite-work-click-tips img {
  width: 130px;
  position: absolute;
  right: 15px;
}

#kite-captcha .kite-work-click-tips span {
  font-size: 20px;
  display: inline-block;
  height: 40px;
  line-height: 40px;
  position: absolute
}

#kite-captcha .kite-captcha-content #kite-bg-img-click-mask {
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0
}

#kite-captcha .kite-captcha-content #kite-bg-img-click-mask .click-span {
  position: absolute;
  left: 0;
  top: 0;
  border-radius: 50px;
  background-color: #409eff;
  width: 20px;
  height: 20px;
  text-align: center;
  line-height: 20px;
  color: #fff;
  border: 2px solid #fff
}

/** word_click css end **/


</style>
